﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using JiraGenCommon.Constants;
using JiraGenCommon.jiraSoapServices;

namespace JiraGenCommon.JiraServices
{
    public sealed class JiraService
    {
        static JiraService instance = null;
        static readonly object padlock = new object();
        private static string svcToken = string.Empty;

        JiraService()
        {
        }

        public static JiraService Instance
        {
            get
            {
                lock (padlock)
                {
                    return instance ?? (instance = new JiraService());
                }
            }
        }

        public RemoteProject[] GetProjects()
        {
            var jiraSoapSvc = new JiraSoapServiceService();
            return jiraSoapSvc.getProjectsNoSchemes(GetToken(jiraSoapSvc));
        }

        public RemoteIssue CreateIssue(string project, string summary, string des,
            string assignee, string issueType, string fixVersion, string devEstimate)
        {
            var remoteVersion = new RemoteVersion {id = fixVersion};

            var listRv = new RemoteVersion[] { remoteVersion };

            var remoteIssue = new RemoteIssue
            {
                project = project,
                summary = summary,
                description = des,
                assignee = assignee,
                type = issueType,
                fixVersions = listRv
            };

            var jiraSoapSvc = new JiraSoapServiceService();
            var jiraIssue = CreateIssue(jiraSoapSvc, svcToken, remoteIssue);

            if (!string.IsNullOrEmpty(devEstimate))
            {
                // Set estimate of time needed to complete issue
                var actionParams = new RemoteFieldValue[] { new RemoteFieldValue { id = "timetracking", values = 
                    new string[] { UtilsHelper.RefineEstimationToDefault(devEstimate) } } };
                jiraSoapSvc.updateIssue(GetToken(jiraSoapSvc), jiraIssue.key, actionParams);
            }

            return jiraIssue;
        }

        public RemoteIssue CreateIssue(JiraSoapServiceService jiraSoapSvc, string token, RemoteIssue issue)
        {
            return jiraSoapSvc.createIssue(GetToken(jiraSoapSvc), issue);
        }

        public RemoteIssue CreateSubTask(string projectKey, string summary, string des, string assignee
            , string devEstimate, string parentKey, string issueType, string fixVersion)
        {
            var remoteVersion = new RemoteVersion { id = fixVersion };

            var listRv = new RemoteVersion[] { remoteVersion };

            var remoteIssue = new RemoteIssue
                                  {
                                      project = projectKey,
                                      summary = summary,
                                      description = des,
                                      assignee = assignee,
                                      type = issueType,
                                      fixVersions = listRv
                                  };

            var jiraSoapSvc = new JiraSoapServiceService();
            var subTask = CreateSubTask(jiraSoapSvc, remoteIssue, parentKey);

            if (!string.IsNullOrEmpty(devEstimate))
            {
                // Set estimate of time needed to complete issue
                var actionParams = new RemoteFieldValue[] { new RemoteFieldValue { id = "timetracking", values = 
                    new string[] { UtilsHelper.RefineEstimationToDefault(devEstimate) } } };
                jiraSoapSvc.updateIssue(GetToken(jiraSoapSvc), subTask.key, actionParams);
            }

            return subTask;
        }

        private RemoteIssue CreateSubTask(JiraSoapServiceService jiraSoapSvc, RemoteIssue issue, string parentKey)
        {
            return jiraSoapSvc.createIssueWithParent(GetToken(jiraSoapSvc), issue, parentKey);
        }

        public RemoteIssueType[] GetIssueTypes()
        {
            var jiraSoapSvc = new JiraSoapServiceService();
            return jiraSoapSvc.getIssueTypes(GetToken(jiraSoapSvc));
        }

        public RemoteField[] GetCustomValues()
        {
            var jiraSoapSvc = new JiraSoapServiceService();
            var remoteFields = jiraSoapSvc.getCustomFields(GetToken(jiraSoapSvc));
            return remoteFields;
        }

        public RemoteVersion[] GetVersions(string projectKey)
        {
            var jiraSoapSvc = new JiraSoapServiceService();
            var remoteVersions = jiraSoapSvc.getVersions(GetToken(jiraSoapSvc), projectKey);
            return remoteVersions;
        }

        public RemoteIssue[] GetUserStorySubTasks(string parentKey)
        {
            try
            {
                var jqlQuery = string.Format("parent=\"{0}\"", parentKey);
                return GetIssuesFromJqlSearch(jqlQuery, 5);
            }
            catch (Exception)
            {
                return null;
            }
            
        }

        private RemoteIssue[] GetIssuesFromJqlSearch(string jqlQuery, int returnNumber)
        {
            var jiraSoapSvc = new JiraSoapServiceService();
            return jiraSoapSvc.getIssuesFromJqlSearch(GetToken(jiraSoapSvc), jqlQuery, returnNumber);
        }

        public Dictionary<string, string> GetStatuses()
        {
            var jiraSoapSvc = new JiraSoapServiceService();
            var statuses = jiraSoapSvc.getStatuses(GetToken(jiraSoapSvc));
            return statuses == null ? new Dictionary<string, string>() : 
                statuses.ToDictionary(status => status.id, status => status.name);
        }

        public RemoteIssue GetIssueById(string issueId)
        {
            try
            {
                var jiraSoapSvc = new JiraSoapServiceService();
                return jiraSoapSvc.getIssueById(GetToken(jiraSoapSvc), issueId);
            }
            catch (Exception)
            {
                // write log here
                return null;
            }
        }

        public RemoteIssue GetIssue(string issueKey)
        {
            try
            {
                var jiraSoapSvc = new JiraSoapServiceService();
                return jiraSoapSvc.getIssue(GetToken(jiraSoapSvc), issueKey);
            }
            catch (Exception)
            {
                // write log here
                return null;
            }
        }

        public RemoteWorklog[] GetWorklogs(string issueKey)
        {
            try
            {
                var jiraSoapSvc = new JiraSoapServiceService();
                return jiraSoapSvc.getWorklogs(GetToken(jiraSoapSvc), issueKey);
            }
            catch (Exception)
            {
                // write log here
                return null;
            }
        }

        private static string GetToken(JiraSoapServiceService jiraSoapService)
        {
            const string userName = "admin"; //GetAppConfigValue("jira_user");
            const string password = "P@ssword123"; //"GetAppConfigValue("jira_user_password");
            return jiraSoapService.login(userName, password);
        }
    }
}
